// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OrderEventArgs.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.Forge.Events
{
    #region Using Directives

    using System;

    using Org.OpenTrader.Framework.Events;
    using Org.OpenTrader.Framework.Forge.Enums;

    #endregion

    /// <summary>
    /// The order event args base.
    /// </summary>
    [Serializable]
    public abstract class OrderEventArgs : DispatchableEventArgs
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="OrderEventArgs"/> class.
        /// </summary>
        /// <param name="orderId">
        /// The orderId.
        /// </param>
        public OrderEventArgs(Guid orderId)
            : base(orderId)
        {
        }

        #endregion

        /// <summary>
        /// The connection status.
        /// </summary>
        [Serializable]
        public class ConnectionStatus : OrderEventArgs
        {
            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="ConnectionStatus"/> class.
            /// </summary>
            /// <param name="connectionArgs">
            /// The Connection args.
            /// </param>
            public ConnectionStatus(ConnectionEventArgs connectionArgs)
                : base(Guid.Empty)
            {
                this.ConnectionArgs = connectionArgs;
            }

            #endregion

            #region Properties

            /// <summary>
            /// Gets ConnectionArgs.
            /// </summary>
            public ConnectionEventArgs ConnectionArgs { get; private set; }

            #endregion

            #region Public Methods

            /// <summary>
            /// The to string.
            /// </summary>
            /// <returns>
            /// The to string.
            /// </returns>
            public override string ToString()
            {
                return string.Format("ConnectionStatus[ConnectionArgs={0}]", this.ConnectionArgs);
            }

            #endregion
        }

        /// <summary>
        /// The order error event args.
        /// </summary>
        [Serializable]
        public class Error : OrderEventArgs
        {
            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderEventArgs.Error"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The orderId.
            /// </param>
            /// <param name="errorMessage">
            /// The errorMessage.
            /// </param>
            public Error(Guid orderId, string errorMessage)
                : base(orderId)
            {
                this.ErrorMessage = errorMessage;
            }

            #endregion

            #region Properties

            /// <summary>
            /// Gets or sets ErrorMessage.
            /// </summary>
            public string ErrorMessage { get; set; }

            #endregion

            #region Public Methods

            /// <summary>
            /// The to string.
            /// </summary>
            /// <returns>
            /// The to string.
            /// </returns>
            public override string ToString()
            {
                return string.Format("OrderEventArgs.Error[OrderID={0};ErrorMessage={1}]", this.ObjectID, this.ErrorMessage);
            }

            #endregion
        }

        /// <summary>
        /// The order execution event args.
        /// </summary>
        [Serializable]
        public class Execution : OrderEventArgs
        {
            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="Execution"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The order id.
            /// </param>
            /// <param name="time">
            /// The time.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="price">
            /// The price.
            /// </param>
            /// <param name="quantity">
            /// The quantity.
            /// </param>
            /// <param name="remainingQuantity">
            /// The remaining quantity.
            /// </param>
            public Execution(Guid orderId, DateTime time, EOrderWay way, double price, int quantity, int remainingQuantity)
                : base(orderId)
            {
                this.Time = time;
                this.Way = way;
                this.Price = price;
                this.Quantity = quantity;
                this.RemainingQuantity = remainingQuantity;
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="Execution"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The order id.
            /// </param>
            /// <param name="time">
            /// The time.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="price">
            /// The price.
            /// </param>
            /// <param name="quantity">
            /// The quantity.
            /// </param>
            /// <param name="remainingQuantity">
            /// The remaining quantity.
            /// </param>
            /// <param name="counterparty">
            /// The counterparty.
            /// </param>
            public Execution(Guid orderId, DateTime time, EOrderWay way, double price, int quantity, int remainingQuantity, string counterparty)
                : base(orderId)
            {
                this.Time = time;
                this.Way = way;
                this.Price = price;
                this.Quantity = quantity;
                this.RemainingQuantity = remainingQuantity;
                this.Counterparty = counterparty;
            }

            #endregion

            #region Properties

            /// <summary>
            /// Gets Counterparty.
            /// </summary>
            public string Counterparty { get; private set; }

            /// <summary>
            /// Gets Price.
            /// </summary>
            public double Price { get; private set; }

            /// <summary>
            /// Gets Quantity.
            /// </summary>
            public int Quantity { get; private set; }

            /// <summary>
            /// Gets RemainingQuantity.
            /// </summary>
            public int RemainingQuantity { get; private set; }

            /// <summary>
            /// Execution Time
            /// </summary>
            public DateTime Time { get; private set; }

            /// <summary>
            /// Gets Way.
            /// </summary>
            public EOrderWay Way { get; private set; }

            #endregion

            #region Public Methods

            /// <summary>
            /// The to string.
            /// </summary>
            /// <returns>
            /// The to string.
            /// </returns>
            public override string ToString()
            {
                return string.Format(
                    "OrderEventArgs.Execution[OrderID={0};Price={1};Quantity={2};RemainingQuantity={3}]", 
                    this.ObjectID, 
                    this.Price, 
                    this.Quantity, 
                    this.RemainingQuantity);
            }

            #endregion
        }

        /// <summary>
        /// The inventory event args.
        /// </summary>
        [Serializable]
        public class Inventory : OrderEventArgs
        {
            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderEventArgs.Inventory"/> class. 
            /// The inventory event args.
            /// </summary>
            /// <param name="orderId">
            /// </param>
            /// <param name="way">
            /// </param>
            /// <param name="price">
            /// </param>
            /// <param name="quantity">
            /// </param>
            /// <param name="reset">
            /// </param>
            public Inventory(Guid orderId, EOrderWay way, double price, int quantity, bool reset)
                : base(orderId)
            {
                this.Way = way;
                this.Price = price;
                this.Quantity = quantity;
                this.Reset = reset;
            }

            #endregion

            #region Properties

            /// <summary>
            /// Gets Price.
            /// </summary>
            public double Price { get; private set; }

            /// <summary>
            /// Gets Quantity.
            /// </summary>
            public int Quantity { get; private set; }

            /// <summary>
            /// Gets Reset
            /// </summary>
            public bool Reset { get; private set; }

            /// <summary>
            /// Gets Way.
            /// </summary>
            public EOrderWay Way { get; private set; }

            #endregion

            #region Public Methods

            /// <summary>
            /// The to string.
            /// </summary>
            /// <returns>
            /// The to string.
            /// </returns>
            public override string ToString()
            {
                return string.Format("OrderEventArgs.Inventory[Price={0};Quantity={1};Way{2}]", this.Price, this.Quantity, this.Way.ToString());
            }

            #endregion
        }

        /// <summary>
        /// The order status event args.
        /// </summary>
        [Serializable]
        public class Status : OrderEventArgs
        {
            #region Constants and Fields

            /// <summary>
            /// The tostring.
            /// </summary>
            private readonly string tostring;

            #endregion

            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderEventArgs.Status"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The orderId.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="status">
            /// The status.
            /// </param>
            public Status(Guid orderId, EOrderWay way, EOrderStatus status)
                : base(orderId)
            {
                this.CancelQuantity = 0;
                this.RequestedQuantity = 0;
                this.RemainingQuantity = 0;
                this.RequestedPrice = 0.0;
                this.OrderStatus = status;
                this.Way = way;

                this.tostring =
                    string.Format(
                        "OrderEventArgs.Status[OrderID={0};OrderStatus={1};CancelQuantity={2};RequestedQuantity={3};RemainingQuantity={4};RequestedPrice={5}]", 
                        this.ObjectID, 
                        this.OrderStatus, 
                        this.CancelQuantity, 
                        this.RequestedQuantity, 
                        this.RemainingQuantity, 
                        this.RequestedPrice);
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderEventArgs.Status"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The orderId.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="status">
            /// The status.
            /// </param>
            /// <param name="cancelQuantity">
            /// The cancelQuantity.
            /// </param>
            public Status(Guid orderId, EOrderWay way, EOrderStatus status, int cancelQuantity)
                : base(orderId)
            {
                this.CancelQuantity = cancelQuantity;
                this.OrderStatus = status;
                this.Way = way;

                this.tostring = string.Format(
                    "OrderEventArgs.Status[OrderID={0};OrderStatus={1};CancelQuantity={2}]", this.ObjectID, this.OrderStatus, this.CancelQuantity);
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="OrderEventArgs.Status"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The orderId.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="status">
            /// The status.
            /// </param>
            /// <param name="requestedQuantity">
            /// The requestedQuantity.
            /// </param>
            /// <param name="remainingQuantity">
            /// The remainingQuantity.
            /// </param>
            /// <param name="requestedPrice">
            /// The requestedPrice.
            /// </param>
            public Status(Guid orderId, EOrderWay way, EOrderStatus status, int requestedQuantity, int remainingQuantity, double requestedPrice)
                : base(orderId)
            {
                this.RequestedQuantity = requestedQuantity;
                this.RequestedPrice = requestedPrice;
                this.RemainingQuantity = remainingQuantity;
                this.OrderStatus = status;
                this.Way = way;

                this.tostring = string.Format(
                    "OrderEventArgs.Status[OrderID={0};OrderStatus={1};CancelQuantity={2}]", this.ObjectID, this.OrderStatus, this.CancelQuantity);
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="Status"/> class.
            /// </summary>
            /// <param name="orderId">
            /// The orderId.
            /// </param>
            /// <param name="way">
            /// The way.
            /// </param>
            /// <param name="status">
            /// The status.
            /// </param>
            /// <param name="rejectReason">
            /// The rejectReason.
            /// </param>
            public Status(Guid orderId, EOrderWay way, EOrderStatus status, string rejectReason)
                : base(orderId)
            {
                this.RejectReason = rejectReason;
                this.OrderStatus = status;
                this.Way = way;

                this.tostring = string.Format(
                    "OrderEventArgs.Status[OrderID={0};OrderStatus={1};RejectReason={2}]", this.ObjectID, this.OrderStatus, this.RejectReason);
            }

            #endregion

            #region Properties

            /// <summary>
            /// Cancelled quantity if status is Cancel
            /// </summary>
            public int CancelQuantity { get; set; }

            /// <summary>
            /// Status
            /// </summary> 
            public EOrderStatus OrderStatus { get; set; }

            /// <summary>
            /// Reject reason if status is reject
            /// </summary>
            public string RejectReason { get; set; }

            /// <summary>
            /// Remaining quantity if status is New order / Modify order
            /// </summary>
            public int RemainingQuantity { get; set; }

            /// <summary>
            /// Requested price if status is New order / Modify order
            /// </summary>
            public double RequestedPrice { get; set; }

            /// <summary>
            /// Requested quantity if status is New order / Modify order
            /// </summary>
            public int RequestedQuantity { get; set; }

            /// <summary>
            /// Gets Way.
            /// </summary>
            public EOrderWay Way { get; private set; }

            #endregion

            #region Public Methods

            /// <summary>
            /// The to string.
            /// </summary>
            /// <returns>
            /// The to string.
            /// </returns>
            public override string ToString()
            {
                return this.tostring;
            }

            #endregion
        }
    }
}